﻿using System;
using System.Net;
using System.Windows;
using Windows.Foundation;
using Windows.UI.Xaml;

namespace BlueRoseGames.Controls.Text
{
    public sealed class PolarTransform : Transform
    {
        #region DependencyProperties
        private double _centerX = 0;
        private double _centerY = 0;
        private double _angle = 0;
        private double _angleStretch = 1;
        private double _radiusStretch = 1;
        private double _radiusX = 50;
        private double _radiusY = 50;
        private Direction _textDirection = Direction.Clockwise;

        public static readonly DependencyProperty AngleProperty = DependencyProperty.Register("Angle", typeof(double), typeof(PolarTransform), new PropertyMetadata(0d, OnAngleChanged));
        public double Angle
        {
            get { return (double)GetValue(AngleProperty); }
            set { SetValue(AngleProperty, value); }
        }

        public static readonly DependencyProperty AngleStretchProperty = DependencyProperty.Register("AngleStretch", typeof(double), typeof(PolarTransform), new PropertyMetadata(1d, OnAngleStretchChanged));
        public double AngleStretch
        {
            get { return (double)GetValue(AngleStretchProperty); }
            set { SetValue(AngleStretchProperty, value); }
        }

        public static readonly DependencyProperty CenterXProperty = DependencyProperty.Register("CenterX", typeof(double), typeof(PolarTransform), new PropertyMetadata(0d, OnCenterXChanged));
        public double CenterX
        {
            get { return (double)GetValue(CenterXProperty); }
            set { SetValue(CenterXProperty, value); }
        }

        public static readonly DependencyProperty CenterYProperty = DependencyProperty.Register("CenterY", typeof(double), typeof(PolarTransform), new PropertyMetadata(0d, OnCenterYChanged));
        public double CenterY
        {
            get { return (double)GetValue(CenterYProperty); }
            set { SetValue(CenterYProperty, value); }
        }

        public static readonly DependencyProperty RadiusXProperty = DependencyProperty.Register("RadiusX", typeof(double), typeof(PolarTransform), new PropertyMetadata(50d, OnRadiusXChanged));
        public double RadiusX
        {
            get { return (double)GetValue(RadiusXProperty); }
            set { SetValue(RadiusXProperty, value); }
        }

        public static readonly DependencyProperty RadiusYProperty = DependencyProperty.Register("RadiusY", typeof(double), typeof(PolarTransform), new PropertyMetadata(50d, OnRadiusYChanged));
        public double RadiusY
        {
            get { return (double)GetValue(RadiusYProperty); }
            set { SetValue(RadiusYProperty, value); }
        }

        public static readonly DependencyProperty RadiusStretchProperty = DependencyProperty.Register("RadiusStretch", typeof(double), typeof(PolarTransform), new PropertyMetadata(1d, OnRadiusStretchChanged));
        public double RadiusStretch
        {
            get { return (double)GetValue(RadiusStretchProperty); }
            set { SetValue(RadiusStretchProperty, value); }
        }

        public static readonly DependencyProperty TextDirectionProperty = DependencyProperty.Register("TextDirection", typeof(Direction), typeof(PolarTransform), new PropertyMetadata(Direction.Clockwise, OnTextDirectionChanged));
        public Direction TextDirection
        {
            get { return (Direction)GetValue(TextDirectionProperty); }
            set { SetValue(TextDirectionProperty, value); }
        }

        private static void OnCenterXChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var pt = (PolarTransform)dependencyObject;
            pt._centerX = (double)e.NewValue;
            pt.Changed = true;
        }

        private static void OnCenterYChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var pt = (PolarTransform)dependencyObject;
            pt._centerY = (double)e.NewValue;
            pt.Changed = true;
        }

        private static void OnRadiusXChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var pt = (PolarTransform)dependencyObject;
            pt._radiusX = (double)e.NewValue;
            pt.Changed = true;
        }
                
        private static void OnRadiusYChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var pt = (PolarTransform)dependencyObject;
            pt._radiusY = (double)e.NewValue;
            pt.Changed = true;
        }

        private static void OnRadiusStretchChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var pt = (PolarTransform)dependencyObject;
            pt._radiusStretch = (double)e.NewValue;
            pt.Changed = true;
        }

        private static void OnAngleChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var pt = (PolarTransform)dependencyObject;
            pt._angle = (double)e.NewValue;
            pt.Changed = true;
        } 

        private static void OnAngleStretchChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var pt = (PolarTransform)dependencyObject;
            pt._angleStretch = (double)e.NewValue;
            pt.Changed = true;
        }        

        private static void OnTextDirectionChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var pt = (PolarTransform)dependencyObject;
            pt._textDirection = (Direction)e.NewValue;
            pt.Changed = true;
        }  
        #endregion


        public override Point TransformPoint(Point p)
        {
            Point ret = new Point();
            double rx = 0;
            double ry=0;
            if (TextDirection == Direction.Clockwise)
            {
                rx = _radiusX - p.Y * _radiusStretch;
                ry = _radiusY - p.Y * _radiusStretch;
            }
            else
            {
                rx = _radiusX + p.Y * _radiusStretch;
                ry = _radiusY + p.Y * _radiusStretch;
            }
            double theta = (((_angle * Math.PI) / 180d) + ((-p.X * _angleStretch) / 100));
            if (_textDirection == Direction.Clockwise)
            {
                theta = -theta;
            }
            ret.Y = Math.Sin(theta) * (ry) + _centerY;
            ret.X = Math.Cos(theta) * (rx) + _centerX;
            return ret;
        }

        public enum Direction
        {
            Clockwise,
            CounterClockwise
        }
    }
}
